home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / et / et3_0-a1.lha / et3 / src / Box.C < prev    next >
C/C++ Source or Header  |  1992-05-29  |  8KB  |  406 lines

  1. #ifdef __GNUG__
  2. #pragma implementation
  3. #endif
  4.  
  5. #include "Box.h"
  6.  
  7. #include "Class.h"
  8. #include "Collection.h"
  9. #include "Math.h"
  10.  
  11. struct rcinfo {
  12.     int wd, ht, bs;
  13.     int hfixed, vfixed;
  14. };
  15.  
  16. //---- Box ---------------------------------------------------------------------
  17.  
  18. NewMetaImpl(Box,CompositeVObject, (T(colsrows), T(gap), TE(align)));
  19.  
  20. Box::Box(int id, Point cr, Point g, VObjAlign a)
  21.                     : CompositeVObject(id, (SeqCollection*)0)
  22. {
  23.     colsrows= cr;
  24.     gap= g;
  25.     align= a;
  26. }
  27.  
  28. Box::Box(int id, Point cr, Point g, VObjAlign a, VObject *va_(vop), ...)
  29.                     : CompositeVObject(id, (SeqCollection*)0)
  30. {
  31.     va_list ap;
  32.     va_start(ap, va_(vop));
  33.     SetItems(va_(vop), ap);
  34.     colsrows= cr;
  35.     gap= g;
  36.     align= a;
  37.     va_end(ap);
  38. }
  39.  
  40. Box::Box(int id, Point cr, Point g, VObjAlign a, SeqCollection *sc)
  41.                             : CompositeVObject(id, sc)
  42. {
  43.     colsrows= cr;
  44.     gap= g;
  45.     align= a;
  46. }
  47.  
  48. Box::Box(int id, Point cr, Point g, VObjAlign a, va_list ap)
  49.                             : CompositeVObject(id, ap)
  50. {
  51.     colsrows= cr;
  52.     gap= g;
  53.     align= a;
  54. }
  55.  
  56. void Box::SetAlign(VObjAlign a)
  57. {
  58.     align= a;
  59. }
  60.  
  61. void Box::SetGap(Point g)
  62. {
  63.     gap= g;
  64. }
  65.  
  66. void Box::SetColsRowsSize(Point cr)
  67. {
  68.     colsrows= cr;
  69. }
  70.  
  71. int Box::expandCnt()
  72. {
  73.     return 0;
  74. }
  75.  
  76. Point Box::ColsRowsSize()
  77. {
  78.     int n= Size();
  79.     if (colsrows.y <= 0 && colsrows.x <= 0) {
  80.     int c= Math::Sqrt(n);
  81.     return Point(c, (n-1)/c+1);
  82.     }
  83.     if (colsrows.y <= 0)
  84.     return Point(colsrows.x, (n-1)/colsrows.x+1);
  85.     if (colsrows.x <= 0)
  86.     return Point((n-1)/colsrows.y+1, colsrows.y);
  87.     return colsrows;
  88. }
  89.  
  90. Metric Box::getMinSize(Point &rc, rcinfo *rci)
  91. {
  92.     register int x, y;
  93.     Point total(-gap);
  94.  
  95.     getGrid(rc, rci);
  96.     for (x= 0; x < rc.x; x++)
  97.     total.x+= rci[x].wd+gap.x;
  98.     for (y= 0; y < rc.y; y++)
  99.     total.y+= rci[y].ht+gap.y;
  100.     
  101.     if (align & eVObjVBase)
  102.     return Metric(total, rci[0].bs);
  103.     if (Size() > 0)
  104.     return Metric(total, At(0)->Base());
  105.     return Metric(total);
  106. }
  107.  
  108. void Box::getGrid(Point &rc, rcinfo *rci)
  109. {
  110.     Iter next(MakeIterator());
  111.     register VObject *vop;
  112.     register int x, y, hh, bb, maxwd= 0, maxht= 0, n;
  113.     Metric m;
  114.     bool hexpand= align & eVObjHExpand,
  115.      vexpand= (align & eVObjVExpand) && !(align & eVObjVBase);
  116.     
  117.     for (x= 0; x < rc.x; x++)
  118.     rci[x].hfixed= 0;
  119.     for (y= 0; y < rc.y; y++)
  120.     rci[y].vfixed= 0;
  121.  
  122.     for (y= 0; y < rc.y; y++) {
  123.     hh= bb= 0;
  124.     for (x= 0; x < rc.x; x++) {
  125.         if (vop= (VObject*) next()) {
  126.         m= vop->GetMinSize();
  127.         if (align & eVObjVBase) {
  128.             hh= Math::Max(hh, m.Base());
  129.             int eb= m.Height()-m.Base();
  130.             bb= Math::Max(bb, eb);
  131.         } else {
  132.             hh= Math::Max(hh, m.extent.y);
  133.         }
  134.         rci[x].wd= Math::Max(rci[x].wd, m.Width());
  135.         maxwd= Math::Max(maxwd, m.Width());
  136.         if (!hexpand || vop->TestFlag(eVObjHFixed))
  137.             rci[x].hfixed++;
  138.         if (!vexpand || vop->TestFlag(eVObjVFixed))
  139.             rci[y].vfixed++;
  140.         }
  141.         
  142.     }
  143.     rci[y].ht= hh+bb;
  144.     rci[y].bs= hh;
  145.     maxht= Math::Max(maxht, hh+bb);
  146.     }
  147.     
  148.     for (x= 0; x < rc.x; x++) {
  149.     if (rci[x].hfixed >= rc.y)
  150.         rci[x].hfixed= 1;
  151.     else
  152.         rci[x].hfixed= 0;
  153.     }
  154.     for (y= 0; y < rc.y; y++) {
  155.     if (rci[y].vfixed >= rc.x)
  156.         rci[y].vfixed= 1;
  157.     else
  158.         rci[y].vfixed= 0;
  159.     }
  160.     /*
  161.     for (x= 0; x < rc.x; x++) {
  162.     if (rci[x].hfixed > 0)
  163.         rci[x].hfixed= 1;
  164.     else
  165.         rci[x].hfixed= 0;
  166.     }
  167.     for (y= 0; y < rc.y; y++) {
  168.     if (rci[y].vfixed > 0)
  169.         rci[y].vfixed= 1;
  170.     else
  171.         rci[y].vfixed= 0;
  172.     }
  173.     */
  174.     
  175.     if ((align & eVObjHGapExpand) && rc.x > 1) {
  176.     ResetFlag(eVObjHFixed);
  177.     } else {
  178.     for (n= x= 0; x < rc.x; x++)
  179.         if (rci[x].hfixed)
  180.         n++;
  181.     SetFlag(eVObjHFixed, n >= rc.x);
  182.     }
  183.     
  184.     if ((align & eVObjVGapExpand) && rc.y > 1) {
  185.     ResetFlag(eVObjVFixed);
  186.     } else {
  187.     for (n= y= 0; y < rc.y; y++)
  188.         if (rci[y].vfixed)
  189.         n++;
  190.     SetFlag(eVObjVFixed, n >= rc.y);
  191.     }
  192.     
  193.     if (align & eVObjHEqual)
  194.     for (x= 0; x < rc.x; x++)
  195.         rci[x].wd= maxwd;
  196.     if (align & eVObjVEqual)
  197.     for (y= 0; y < rc.y; y++)
  198.         rci[y].ht= maxht;
  199. }
  200.  
  201. void Box::expand(Point &rc, rcinfo *rci, Point &g, Point &r)
  202. {
  203.     register x, y, div, rest;
  204.     int n;
  205.  
  206.     g= gap;
  207.     r= gPoint0;
  208.     
  209.     Point diff= GetExtent()-getMinSize(rc, rci).extent;
  210.     
  211.     if (diff.x > 0) {
  212.     if (align & eVObjHGapExpand) {
  213.         if (rc.x > 1) {
  214.         g.x= diff.x/(rc.x-1);
  215.         r.x= diff.x-g.x*(rc.x-1);
  216.         g.x+= gap.x;
  217.         }
  218.     }
  219.     if (align & eVObjHExpand) {
  220.         for (n= x= 0; x < rc.x; x++)
  221.         if (!rci[x].hfixed)   // col not hfixed
  222.             n++;
  223.         if (n > 0) {
  224.         div= diff.x/n;
  225.         rest= diff.x-div*n;
  226.         for (x= 0; x < rc.x; x++) {
  227.             if (!rci[x].hfixed) {
  228.             rci[x].wd+= div;
  229.             if (rest > 0) {
  230.                 rci[x].wd++;
  231.                 rest--;
  232.             }
  233.             }
  234.         }
  235.         }
  236.     }
  237.     }
  238.  
  239.     if (diff.y > 0) {
  240.     if (align & eVObjVGapExpand) {
  241.         if (rc.y > 1) {
  242.         g.y= diff.y/(rc.y-1);
  243.         r.y= diff.y-g.y*(rc.y-1);
  244.         g.y+= gap.y;
  245.         }
  246.     }
  247.     if (align & eVObjVExpand) {
  248.         for (n= y= 0; y < rc.y; y++)
  249.         if (!rci[y].vfixed)   // row not vfixed
  250.             n++;
  251.         if (n > 0) {
  252.         div= diff.y/n;
  253.         rest= diff.y-div*n;
  254.         for (y= 0; y < rc.y; y++) {
  255.             if (!rci[y].vfixed) {
  256.             rci[y].ht+= div;
  257.             if (rest > 0) {
  258.                 rci[y].ht++;
  259.                 rest--;
  260.             }
  261.             }
  262.         }
  263.         }
  264.     }
  265.     }
  266. }
  267.  
  268. Metric Box::GetMinSize()
  269. {
  270.     Point rc= ColsRowsSize();
  271.     rcinfo *rci= new rcinfo[Math::Max(rc.x, rc.y)];
  272.     Metric m= getMinSize(rc, rci);
  273.     delete rci;
  274.     return m;
  275. }
  276.  
  277. void Box::SetOrigin(Point at)
  278. {
  279.     Iter next(MakeIterator());
  280.     register VObject *vop;
  281.     register int x, y;
  282.     Point g, r, rr, a, rc= ColsRowsSize();
  283.     rcinfo *rci= new rcinfo[Math::Max(rc.x, rc.y)];
  284.     
  285.     expand(rc, rci, g, r);
  286.  
  287.     VObject::SetOrigin(at);
  288.     
  289.     a.y= at.y;
  290.     rr.y= r.y;
  291.     for (y= 0; y < rc.y; y++) {
  292.     a.x= at.x;
  293.     rr.x= r.x;
  294.     for (x= 0; x < rc.x; x++) {
  295.         if (vop= (VObject*) next())
  296.         vop->Align(a, Metric(rci[x].wd, rci[y].ht, rci[y].bs), align);
  297.         a.x+= rci[x].wd + g.x;
  298.         if (rr.x > 0) {
  299.         a.x++;
  300.         rr.x--;
  301.         }
  302.     }
  303.     a.y+= rci[y].ht + g.y;
  304.     if (rr.y > 0) {
  305.         a.y++;
  306.         rr.y--;
  307.     }
  308.     }
  309.     delete rci;
  310. }
  311.  
  312. void Box::SetExtent(Point ee)
  313. {
  314.     Iter next(MakeIterator());
  315.     register VObject *vop;
  316.     register x, y;
  317.     Point e, g, r, rc= ColsRowsSize();
  318.     rcinfo *rci= new rcinfo[Math::Max(rc.x, rc.y)];
  319.     bool hexpand= align & (eVObjHExpand|eVObjHEqual),
  320.      vexpand= (align & (eVObjVExpand|eVObjVEqual)) && !(align & eVObjVBase);
  321.  
  322.     e= getMinSize(rc, rci).extent;
  323.     if (!TestFlag(eVObjHFixed))
  324.     e.x= ee.x;
  325.     if (!TestFlag(eVObjVFixed) && !(align & eVObjVBase))
  326.     e.y= ee.y;
  327.     VObject::SetExtent(e);
  328.     
  329.     expand(rc, rci, g, r);
  330.     
  331.     for (y= 0; y < rc.y; y++)
  332.     for (x= 0; x < rc.x; x++)
  333.         if (vop= (VObject*) next()) {
  334.         e= vop->GetMinSize().extent;
  335.         if (hexpand && !vop->TestFlag(eVObjHFixed))
  336.             e.x= rci[x].wd;
  337.         if (vexpand && !vop->TestFlag(eVObjVFixed))
  338.             e.y= rci[y].ht;
  339.         vop->SetExtent(e);
  340.         }
  341.  
  342.     delete rci;
  343. }
  344.  
  345. void Box::DrawAll(Rectangle r, bool highlight)
  346. {
  347.     CompositeVObject::DrawAll(r, highlight);
  348. }
  349.  
  350. OStream& Box::PrintOn(OStream &s)
  351. {
  352.     CompositeVObject::PrintOn(s);
  353.     return s << colsrows SP << gap SP << align SP;
  354. }
  355.  
  356. IStream& Box::ReadFrom(IStream &s)
  357. {
  358.     CompositeVObject::ReadFrom(s);
  359.     return s >> colsrows >> gap >> Enum(align);
  360. }
  361.  
  362. //---- HBox --------------------------------------------------------------------
  363.  
  364. NewMetaImpl0(HBox,Box);
  365.  
  366. HBox::HBox(Point g, VObjAlign a) : Box(cIdNone, Point(0,1), g, a)
  367. {
  368. }
  369.  
  370. HBox::HBox(Point g, VObjAlign a, VObject *va_(vop), ...)
  371.                         : Box(cIdNone, Point(0,1), g, a)
  372. {
  373.     va_list ap;
  374.     va_start(ap, va_(vop));
  375.     SetItems(va_(vop), ap);
  376.     va_end(ap);
  377. }
  378.  
  379. HBox::HBox(Point g, VObjAlign a, SeqCollection *c)
  380.                         : Box(cIdNone, Point(0,1), g, a, c)
  381. {
  382. }
  383.  
  384. //---- VBox --------------------------------------------------------------------
  385.  
  386. NewMetaImpl0(VBox,Box);
  387.  
  388. VBox::VBox(Point g, VObjAlign a) : Box(cIdNone, Point(1,0), g, a)
  389. {
  390. }
  391.  
  392. VBox::VBox(Point g, VObjAlign a, VObject *va_(vop), ...)
  393.                         : Box(cIdNone, Point(1,0), g, a)
  394. {
  395.     va_list ap;
  396.     va_start(ap, va_(vop));
  397.     SetItems(va_(vop), ap);
  398.     va_end(ap);
  399. }
  400.  
  401. VBox::VBox(Point g, VObjAlign a, SeqCollection *c)
  402.                         : Box(cIdNone, Point(0,1), g, a, c)
  403. {
  404. }
  405.  
  406.